# -*- coding: utf-8 -*-
from flask.ext.login import login_required, login_user, logout_user, current_user
from login import LoginForm

__author__ = 'gongqf'
import os
import json
from flask import render_template, request, flash, url_for, redirect, jsonify, send_from_directory, make_response, g, \
    session
from gis import app, login_manager, oid
from models import db, card, User, ROLE_USER
from math import ceil
from sqlalchemy import or_
from datetime import datetime


def todict(items, usenone=True, delkey=None, repkey=None):
    '''
    items:  是把request.form获得的ImmutableMultiDict对象用iteritems取得
    usenone:是否把空值('')转换为None返回,默认转换为None
    delkey: 删除指定的key,比如多余获取的input值,传入值可以是tuple或list,默认不删除
    repkey: 用指定的键值新增或替换对应的键值，比如checkbox提交的时候如果uncheck则对应的name字段不会提交，需要手动控制
    '''
    d = {}
    for k, v in items:
        # print k,v
        if v:
            d[k] = v
        elif usenone:
            d[k] = None
    if delkey:
        if type(delkey) == tuple or type(delkey) == list:
            for key in delkey:
                d.pop(key, None)
        else:
            d.pop(delkey, None)
    if repkey:
        for rk in repkey:
            d[rk] = repkey[rk]
    return d


def sarow2dict(rows, emptystr=True):
    def row2dict(row, emptystr=True):
        d = {}
        for column in row.__table__.columns:
            d[column.name] = getattr(row, column.name)
            if emptystr and d[column.name] is None:
                d[column.name] = ''
        return d

    if not rows:
        if rows is None:
            return None
        elif type(rows) == list:
            return []
        elif type(rows) == tuple:
            return ()
        elif type(rows) == dict:
            return {}

    if type(rows) == list:
        # if type(rows)==tuple or type(rows)==list:
        l = []
        for row in rows:
            l.append(row2dict(row))
        return l
    else:
        return row2dict(rows)


def check_form_vaild(card_date, card_dept, card_fibername, card_fibercode, card_fiberlen, card_count, card_use,
                     card_action):
    form_vaild = True
    if card_date.strip() == '':
        flash(u'日期错误', category='error')
        form_vaild = False
    if card_dept.strip() == '':
        form_vaild = False
        flash(u'区域/单位/部门错误', category='error')
    # if card_fibername.strip() =='':
    # form_vaild=False
    #     flash(u'标牌名称错误')
    # if card_fibercode.strip() =='':
    #     form_vaild=False
    #     flash(u'标牌编码错误')
    if card_count.strip() == '' or not card_count.isdigit():
        form_vaild = False
        flash(u'标牌数量错误', category='error')
    if not card_fiberlen.isdigit():
        form_vaild = False
        flash(u'光缆长度错误', category='error')
    # if card_use.strip() =='':
    #     form_vaild=False
    #     flash(u'领用人错误')
    # if card_action.strip() =='':
    #     form_vaild=False
    #     flash(u'经办人错误')
    return form_vaild


@app.route('/')
def index():
    return render_template('base.html', x='hello')


@app.route('/card', methods=['GET', 'POST'])
@app.route('/card/<int:card_id>', methods=['GET', 'POST'])
def Card(card_id=None):
    if request.method == 'POST':
        action = request.form.get('action', None)
        card_date = request.form.get('card_date', None)
        card_dept = request.form.get('card_dept', None)
        card_fibername = request.form.get('card_fibername', None)
        card_fibercode = request.form.get('card_fibercode', None)
        card_fibercore = request.form.get('card_fibercore', None)
        card_fiberlen = request.form.get('card_fiberlen', None)
        card_count = request.form.get('card_count', None)
        card_use = request.form.get('card_use', None)
        card_action = request.form.get('card_action', None)
        card_gis = request.form.get('card_gis')
        card_memo = request.form.get('card_memo', None)
        card_source = request.form.get('card_source', None)
        # print action,card_date,card_gis,request.form.iteritems()
        if card_gis is None:
            card_gis = False
        else:
            card_gis = True
        if not check_form_vaild(card_date=card_date, card_dept=card_dept, card_fibername=card_fibername,
                                card_fibercode=card_fibercode, card_count=card_count, card_use=card_use,
                                card_action=card_action, card_fiberlen=card_fiberlen):
            return redirect(url_for('Card', card_id=card_id))
        if action == u'新增':
            onecard = card(card_date=card_date, card_dept=card_dept, card_fibername=card_fibername,
                           card_fibercode=card_fibercode, card_count=card_count, card_use=card_use,
                           card_action=card_action, card_gis=card_gis, card_memo=card_memo, card_fiberlen=card_fiberlen,
                           card_source=card_source, card_fibercore=card_fibercore)
            db.session.add(onecard)
            flash(u"添加成功")
        if action == u'删除':
            card.query.filter_by(card_id=card_id).delete()
            flash(u'删除成功')
        if action == u'保存':
            card.query.filter_by(card_id=card_id).update(todict(request.form.iteritems(), delkey='action',
                                                                repkey=dict(card_gis=card_gis,
                                                                            card_update=datetime.strftime(
                                                                                datetime.now(), '%Y-%m-%d %H:%M:%S'))))
            flash(u"修改成功")
        db.session.commit()
        # return redirect(url_for('Card'))
    onecard = card.query.filter_by(card_id=card_id).first()
    todaycards = card.query.filter_by(card_date=datetime.strftime(datetime.now(), '%Y-%m-%d')).all()
    return render_template('card.html', onecard=sarow2dict(onecard), cards=sarow2dict(todaycards))


@app.route('/json', methods=['GET'])
def Json():
    depts = []

    for item in db.session.query(card.card_dept.distinct()).order_by(card.card_dept).all():
        if item[0]:
            depts.append(item[0])

    actions = []

    for item in db.session.query(card.card_action.distinct()).order_by(card.card_action).all():
        if item[0]:
            actions.append(item[0])

    uses = []

    for item in db.session.query(card.card_use.distinct()).order_by(card.card_use).all():
        if item[0]:
            uses.append(item[0])

    return app.response_class(
        json.dumps({"depts": depts, "actions": actions, "uses": uses}, indent=None if request.is_xhr else 2),
        mimetype='application/json')


@app.route('/useprint', methods=['GET', 'POST'])
def Useprint():
    # ids=request.form['ids']
    ids = request.values['ids']
    print ids
    ids = ids.split(',')
    cards = card.query.filter(card.card_id.in_(ids)).all()
    print ids, cards
    resp = make_response(render_template('card_useprint.html', cards=sarow2dict(cards)))
    resp.headers['Content-Disposition'] = 'attachment; filename=useprint.doc'
    resp.headers['Content-Type'] = "application/vnd.ms-word"

    return resp


@app.route('/cardprint/<id>', methods=['GET'])
def Cardprint(id):
    print 'id:', id

    def gen_qr_pic(id, txt=''):
        import qrcode

        qr = qrcode.QRCode(version=None, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=12, border=1)
        qr.add_data(txt)
        qr.make(fit=True)  # Generate the QRCode itself

        # im contains a PIL.Image.Image object
        im = qr.make_image()

        # To save it
        print app.config['CARD_FOLDER']
        qr_file = os.path.join(app.config['CARD_FOLDER'], '%s.png' % id)
        im.save(qr_file)
        print qr_file
        return qr_file


    def gen_card_word(card_id, qr_file, card_fibercode='card_fibercode', card_fibername='card_fibername',
                      card_fibercore='card_fibercore', card_date='card_date'):

        from win32com.client import Dispatch, constants, DispatchEx
        # from win32com.client.gencache import EnsureDispatch
        import shutil

        # EnsureDispatch('Word.Application') #makepy 导入Word类库，否则constants无法使用
        # w = win32com.client.Dispatch('Word.Application')
        # 或者使用下面的方法，使用启动独立的进程：
        # w = win32com.client.DispatchEx('Word.Application')
        w = DispatchEx('Word.Application')

        # 后台运行，不显示，不警告
        w.Visible = False
        w.DisplayAlerts = False

        word_template = os.path.join(app.config['CARD_FOLDER'], u'光缆模板.docx')
        word_work = os.path.join(app.config['CARD_FOLDER'],
                                 '%s.docx' % ''.join(map(lambda xx: (hex(ord(xx))[2:]), os.urandom(16))))
        print word_work
        shutil.copy(word_template, word_work)

        # 打开新的文件
        doc = w.Documents.Open(FileName=word_work)
        # doc = w.Documents.Add() # 创建新的文档

        w.Selection.Find.Execute('card_fibercode', False, False, False, False, False, True, 1, True, card_fibercode, 2)
        w.Selection.Find.Execute('card_fibername', False, False, False, False, False, True, 1, True, card_fibername, 2)
        w.Selection.Find.Execute('card_fibercore', False, False, False, False, False, True, 1, True,
                                 'GYTS-%sB1' % card_fibercore, 2)
        w.Selection.Find.Execute('card_date', False, False, False, False, False, True, 1, True, card_date, 2)

        shps = w.ActiveDocument.Shapes

        # shps.AddPicture(qr_file,Left=155,Top=50,Height=75,Width=75)
        shps.AddPicture(qr_file)
        for shp in shps:
            print shp.Left, shp.Top, shp.Height, shp.Width, shp.Line.Visible, shp.Name
        print shps.Count
        shps[0].Left = 146.5
        shps[0].Top = 21
        shps[0].Height = 75
        shps[0].Width = 75
        for shp in shps:
            print shp.Left, shp.Top, shp.Height, shp.Width, shp.Line.Visible, shp.Name
        print shps.Count
        # # 打印
        # # worddoc.PrintOut()
        word_file = os.path.join(app.config['CARD_FOLDER'], '%s.docx' % card_id)
        doc.SaveAs(word_file)
        doc.Close()
        w.Quit()
        print word_file
        os.remove(word_work)
        return word_file

    onecard = card.query.filter_by(card_id=id).first()
    if not onecard:
        flash(u'无此标牌', 'error')
        return redirect(url_for('Card'))
    print onecard.card_id, onecard.card_fibercode
    if not onecard.card_fibercode:
        flash(u'标牌无编码', 'error')
        return redirect(url_for('Card', id=onecard.card_id))
    if not onecard.card_fibercore:
        flash(u'标牌无芯数', 'error')
        return redirect(url_for('Card', id=onecard.card_id))
    if not onecard.card_date:
        flash(u'标牌无日期', 'error')
        return redirect(url_for('Card', id=onecard.card_id))
    qr_pic_file = gen_qr_pic(onecard.card_id, onecard.card_fibercode)
    card_word_file = gen_card_word(onecard.card_id, qr_pic_file, onecard.card_fibercode, onecard.card_fibername,
                                   onecard.card_fibercore, datetime.strftime(onecard.card_date, '%Y-%m'))
    resp = make_response()
    resp.cache_control.no_cache = True
    return send_from_directory(app.config['CARD_FOLDER'], '%s.docx' % onecard.card_id, as_attachment=True)


@app.route('/cards')
def Cards():
    return render_template('cards.html')


def hj(d):
    s = 0
    if d:
        for x in d:
            s += x.card_count
    return s


@app.route('/card_list', methods=['GET'])
def Card_list():
    sc = request.args.get('sc', '')
    inputstart = request.args.get('inputstart', '')
    inputend = request.args.get('inputend', '')
    page = request.args.get('page', 1, type=int)
    pc = request.args.get('pc', 25, type=int)
    gis = request.args.get('gis', '')
    if gis == '0': card_gis = False
    if gis == '1': card_gis = True
    if inputstart == '': inputstart = '1970-1-1'
    if inputend == '': inputend = '2070-1-1'
    if gis == '':
        cards = card.query.filter(or_(card.card_dept.like('%%%s%%' % sc), card.card_fibername.like('%%%s%%' % sc),
                                      card.card_fibercode.like('%%%s%%' % sc), card.card_action.like('%%%s%%' % sc),
                                      card.card_use.like('%%%s%%' % sc), card.card_memo.like('%%%s%%' % sc))).filter(
            card.card_date >= inputstart).filter(card.card_date <= inputend).order_by(card.card_id.desc()).all()
    else:
        cards = card.query.filter(or_(card.card_dept.like('%%%s%%' % sc), card.card_fibername.like('%%%s%%' % sc),
                                      card.card_fibercode.like('%%%s%%' % sc), card.card_action.like('%%%s%%' % sc),
                                      card.card_use.like('%%%s%%' % sc), card.card_memo.like('%%%s%%' % sc))).filter(
            card.card_date >= inputstart).filter(card.card_date <= inputend).filter(card.card_gis == card_gis).order_by(
            card.card_id.desc()).all()
    rows = len(cards)
    sum_card_count = hj(cards)
    if pc == 0:
        pages = 1
        page = 1
    else:
        pages = int(ceil(rows / float(pc)))
        if page <= 0:
            page = 1
        if page > pages:
            page = pages
        offset = pc * (int(page) - 1)
        cards = cards[offset:offset + pc]
        xj_card_count = hj(cards)
    # cards=card.query.order_by(card.card_id.desc()).all()
    return render_template('card_list.html', cards=sarow2dict(cards), rows=rows, pages=pages, page=page, pc=pc,
                           xj_card_count=xj_card_count, sum_card_count=sum_card_count)


@app.before_request
def before_request():
    g.user = current_user


@login_manager.user_loader
def load_user(id):
    return User.query.get(int(id))


@app.route("/login", methods=["GET", "POST"])
@oid.loginhandler
def login():
    if g.user is not None and g.user.is_authenticated():
        return redirect(url_for('index'))
    form = LoginForm()
    if form.validate_on_submit():
        # login and validate the user...
        session['remember_me'] = form.remember_me.data
        return oid.try_login(form.openid.data, ask_for=['nickname', 'email'])
    return render_template("login.html", title='Sign In', form=form, providers=app.config['OPENID_PROVIDERS'])


@oid.after_login
def after_login(resp):
    if resp.email is None or resp.email == "":
        flash('Invalid login. Please try again.')
        return redirect(url_for('login'))
    user = User.query.filter_by(email=resp.email).first()
    if user is None:
        nickname = resp.nickname
        if nickname is None or nickname == "":
            nickname = resp.email.split('@')[0]
        user = User(nickname=nickname, email=resp.email, role=ROLE_USER)
        db.session.add(user)
        db.session.commit()
    remember_me = False
    if 'remember_me' in session:
        remember_me = session['remember_me']
        session.pop('remember_me', None)
    login_user(user, remember=remember_me)
    return redirect(request.args.get('next') or url_for('index'))


@app.route("/settings")
@login_required
def settings():
    pass


@app.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))
